package org.example.sys.controller;

import cn.hutool.core.util.StrUtil;
import com.wf.captcha.SpecCaptcha;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.example.core.Constants;
import org.example.core.utils.VerifyUtil;
import org.example.core.web.Result;
import org.example.sys.config.ConfigProperties;
import org.example.sys.entity.TSysMenu;
import org.example.sys.entity.TSysUser;
import org.example.sys.entity.dto.MenuDTO;
import org.example.sys.entity.dto.UserDTO;
import org.example.sys.entity.param.LoginParam;
import org.example.sys.entity.param.UpdatePasswordParam;
import org.example.sys.entity.result.CaptchaResult;
import org.example.sys.entity.result.LoginResult;
import org.example.sys.security.JwtSubject;
import org.example.sys.security.JwtUtil;
import org.example.sys.service.TSysRoleMenuService;
import org.example.sys.service.TSysUserService;
import org.example.sys.utils.CommonUtil;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * 登录认证控制器
 * @author Calvin
 */
@Tag(name = "登录认证", description = "登录认证")
@RestController
@RequestMapping("/api")
public class MainController extends ApiController {

    @Resource
    private ConfigProperties configProperties;
    @Resource
    private TSysUserService userService;
    @Resource
    private TSysRoleMenuService roleMenuService;
    //@Resource
    //private LoginRecordService loginRecordService;

    private String determineLoginFailureReason(UserDTO user) {
        if (user == null) {
            return Constants.ACCOUNT_NOT_EXIST;
        }
        if (!Objects.equals(user.getStatus(), 0)) {
            return Constants.ACCOUNT_FROZEN;
        }
        return Constants.PASSWORD_ERROR;
    }

    @Operation(summary = "用户登录")
    @PostMapping("/login")
    public Result<LoginResult> login(@RequestBody LoginParam param) {
        String username = param.getUsername();
        UserDTO user = userService.getByUsername(username);
        if (user == null || !Objects.equals(user.getStatus(), 0) ||
                !userService.comparePassword(user.getPassword(), param.getPassword())) {
            return fail(determineLoginFailureReason(user), null);
        }
        //loginRecordService.saveAsync(username, LoginRecord.TYPE_LOGIN, null, tenantId, request);
        String accessToken = JwtUtil.buildToken(new JwtSubject(username),
                configProperties.getTokenExpireTime(), configProperties.getTokenKey());
        return success(Constants.LOGIN_SUCCESS, new LoginResult(accessToken, user));
    }

    @Operation(summary = "用户注册")
    @PostMapping("/register")
    public Result<LoginResult> register(@RequestBody UserDTO user) {
        VerifyUtil.validateObject(user);
        if(userService.saveUser(user)){
            return success(Constants.REGISTER_SUCCESS,null);
        }
        return fail(Constants.REGISTER_ERROR, null);
    }

    @Operation(summary = "获取登录用户信息")
    @GetMapping("/auth/user")
    public Result<UserDTO> userInfo() {
        return success(userService.getByIdRel(getLoginUserId()));
    }

    @Operation(summary = "获取登录用户菜单")
    @GetMapping("/auth/menu")
    public Result<List<MenuDTO>> userMenu() {
        List<MenuDTO> menus = roleMenuService.listMenuByUserId(getLoginUserId(), TSysMenu.TYPE_MENU);
        return success(CommonUtil.toTreeData(menus, 0, MenuDTO::getParentId, MenuDTO::getMenuId, MenuDTO::setChildren));
    }

    @PreAuthorize("hasAuthority('sys:auth:user')")
    @Operation(summary = "修改个人信息")
    @PutMapping("/auth/user")
    public Result<TSysUser> updateInfo(@RequestBody TSysUser user) {
        user.setUserId(getLoginUserId());
        user.setUsername(null);
        user.setPassword(null);
        if (userService.updateById(user)) {
            return success(userService.getByIdRel(user.getUserId()));
        }
        return fail(Constants.SAVE_FAILED, null);
    }

    @PreAuthorize("hasAuthority('sys:auth:password')")
    @Operation(summary = "修改密码")
    @PutMapping("/auth/password")
    public Result<?> updatePassword(@RequestBody UpdatePasswordParam param) {
        if (StrUtil.hasBlank(param.getOldPassword(), param.getPassword())) {
            return fail(Constants.PARAMETER_CANNOT_BE_NULL);
        }
        Long userId = getLoginUserId();
        if (userId == null) {
            return fail(Constants.NOT_LOGGED_IN);
        }
        if (!userService.comparePassword(userService.getById(userId).getPassword(), param.getOldPassword())) {
            return fail(Constants.OLD_PASSWORD_INCORRECT);
        }
        TSysUser user = new TSysUser();
        user.setUserId(userId);
        user.setPassword(userService.encodePassword(param.getPassword()));
        if (userService.updateById(user)) {
            return success(Constants.UPDATE_SUCCESS);
        }
        return fail(Constants.UPDATE_FAILED);
    }

    @Operation(summary = "图形验证码")
    @GetMapping("/captcha")
    public Result<CaptchaResult> captcha() {
        SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5);
        return success(new CaptchaResult(specCaptcha.toBase64(), specCaptcha.text().toLowerCase()));
    }
}